Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / tests / backend / test_reticulum_config_editor.py

Displaying Raw • Download


tests/backend/test_reticulum_config_editor.py bce42bcdce0e7d2c6d78228e864a4cd1d974cc82 (bce42bcd) Text, 6.03 KB

T8b949e# SPDX-License-Identifier: 0BSD

T8b949e"""Tests for the Reticulum Config Editor backend endpoints and helpers."""

Tff7b72import T7ee787json
Tff7b72import T7ee787os
Tff7b72import T7ee787shutil
Tff7b72import T7ee787tempfile
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3MagicMockTb4b4b4, Te6edf3patch

Tff7b72import T7ee787pytest
Tff7b72import T7ee787RNS

Tff7b72from T7ee787meshchatxT7ee787.T7ee787meshchat Tff7b72import Te6edf3ReticulumMeshChat


Tff7b72def Td2a8ff_rns_default_config_text_atTb4b4b4(Te6edf3pathTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
Tff7b72return Te6edf3ReticulumMeshChatTff7b72.Td2a8ff_write_rns_reticulum_default_config_fileTb4b4b4(Te6edf3pathTb4b4b4)


Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8fftemp_dirTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3dir_path Tff7b72= Te6edf3tempfileTff7b72.Td2a8ffmkdtempTb4b4b4(Tb4b4b4)
Tff7b72yield Te6edf3dir_path
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3dir_pathTb4b4b4)


Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8ffmock_rns_minimalTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72with Tb4b4b4(
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffRNS.ReticulumTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3mock_rnsTb4b4b4,
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffRNS.TransportTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffLXMF.LXMRouterTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.meshchat.get_file_pathTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Ta5d6ff"Ta5d6ff/tmp/mock_pathTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4:
Te6edf3mock_rns_instance Tff7b72= Te6edf3mock_rnsTff7b72.Td2a8ffreturn_value
Te6edf3mock_rns_instanceTff7b72.Td2a8ffconfigpath Tff7b72= Ta5d6ff"Ta5d6ff/tmp/mock_configTa5d6ff"
Te6edf3mock_rns_instanceTff7b72.Td2a8ffis_connected_to_shared_instance Tff7b72= Tff7b72False
Te6edf3mock_rns_instanceTff7b72.Td2a8fftransport_enabledTff7b72.Td2a8ffreturn_value Tff7b72= Tff7b72True

Te6edf3mock_id Tff7b72= Te6edf3MagicMockTb4b4b4(Te6edf3specTff7b72=Te6edf3RNSTff7b72.Td2a8ffIdentityTb4b4b4)
Te6edf3mock_idTff7b72.Td2a8ffhash Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6fftest_hash_32_bytes_long_01234567Ta5d6ff"
Te6edf3mock_idTff7b72.Td2a8ffhexhash Tff7b72= Te6edf3mock_idTff7b72.Td2a8ffhashTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)
Te6edf3mock_idTff7b72.Td2a8ffget_private_keyTff7b72.Td2a8ffreturn_value Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6fftest_private_keyTa5d6ff"
Tff7b72yield Te6edf3mock_id


Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8ffapp_instanceTb4b4b4(Te6edf3mock_rns_minimalTb4b4b4, Te6edf3temp_dirTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.meshchat.generate_ssl_certificateTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3instance Tff7b72= Te6edf3ReticulumMeshChatTb4b4b4(
Te6edf3identityTff7b72=Te6edf3mock_rns_minimalTb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3temp_dirTb4b4b4,
Te6edf3reticulum_config_dirTff7b72=Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3temp_dirTb4b4b4, Ta5d6ff"Ta5d6ff.reticulumTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72yield Te6edf3instance


Tff7b72def Td2a8ff_find_handlerTb4b4b4(Te6edf3appTb4b4b4, Te6edf3methodTb4b4b4, Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3route Tff7b72in Te6edf3appTff7b72.Td2a8ffget_routesTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3routeTff7b72.Td2a8ffpath Tff7b72== Te6edf3path Tff7b72and Te6edf3routeTff7b72.Td2a8ffmethod Tff7b72== Te6edf3methodTb4b4b4:
Tff7b72return Te6edf3routeTff7b72.Td2a8ffhandler
Tff7b72raise Tf85149AssertionErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffHandler not found: Tffd700{Te6edf3methodTffd700}Ta5d6ff Tffd700{Te6edf3pathTffd700}Ta5d6ff"Tb4b4b4)


Tff7b72def Td2a8ff_make_requestTb4b4b4(Te6edf3json_bodyTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Te6edf3request Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)

Tff7b72async Tff7b72def Td2a8ff_jsonTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3json_body Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffno json bodyTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3json_body

Te6edf3requestTff7b72.Td2a8ffjson Tff7b72= Te6edf3_json
Tff7b72return Te6edf3request


Tff7b72def Td2a8fftest_write_rns_reticulum_default_config_contains_required_sectionsTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3path Tff7b72= Tffa657strTb4b4b4(Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4)
Te6edf3text Tff7b72= Te6edf3_rns_default_config_text_atTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72assert Ta5d6ff"Ta5d6ff[reticulum]Ta5d6ff" Tff7b72in Te6edf3text
Tff7b72assert Ta5d6ff"Ta5d6ff[interfaces]Ta5d6ff" Tff7b72in Te6edf3text
Tff7b72assert Ta5d6ff"Ta5d6ff[logging]Ta5d6ff" Tff7b72in Te6edf3text
Tff7b72assert Ta5d6ff"Ta5d6ffAutoInterfaceTa5d6ff" Tff7b72in Te6edf3text


Tff7b72def Td2a8fftest_write_rns_reticulum_default_config_is_idempotentTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3p1 Tff7b72= Tffa657strTb4b4b4(Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffaTa5d6ff"Tb4b4b4)
Te6edf3p2 Tff7b72= Tffa657strTb4b4b4(Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffbTa5d6ff"Tb4b4b4)
Te6edf3a Tff7b72= Te6edf3_rns_default_config_text_atTb4b4b4(Te6edf3p1Tb4b4b4)
Te6edf3b Tff7b72= Te6edf3_rns_default_config_text_atTb4b4b4(Te6edf3p2Tb4b4b4)
Tff7b72assert Te6edf3a Tff7b72== Te6edf3b


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_endpoint_get_returns_current_configTb4b4b4(Te6edf3app_instanceTb4b4b4)Tb4b4b4:
Te6edf3_rns_default_config_text_atTb4b4b4(Te6edf3app_instanceTff7b72.Td2a8ff_reticulum_config_file_pathTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3app_instanceTb4b4b4, Ta5d6ff"Ta5d6ffGETTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/reticulum/config/rawTa5d6ff"Tb4b4b4)

Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(Te6edf3_make_requestTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3payload Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3responseTff7b72.Td2a8ffbodyTb4b4b4)
Tff7b72assert Ta5d6ff"Ta5d6ff[reticulum]Ta5d6ff" Tff7b72in Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4]
Tff7b72assert Ta5d6ff"Ta5d6ff[interfaces]Ta5d6ff" Tff7b72in Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4]
Tff7b72assert Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4]Tff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4)


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_endpoint_put_writes_valid_configTb4b4b4(Te6edf3app_instanceTb4b4b4)Tb4b4b4:
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3app_instanceTb4b4b4, Ta5d6ff"Ta5d6ffPUTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/reticulum/config/rawTa5d6ff"Tb4b4b4)

Te6edf3new_content Tff7b72= Tb4b4b4(
Ta5d6ff"Ta5d6ff[reticulum]Tffea00\nTa5d6ff enable_transport = FalseTffea00\nTffea00\nTa5d6ff"
Ta5d6ff"Ta5d6ff[interfaces]Tffea00\nTa5d6ff [[Default Interface]]Tffea00\nTa5d6ff type = AutoInterfaceTffea00\nTa5d6ff"
Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(Te6edf3_make_requestTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4: Te6edf3new_contentTb4b4b4}Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3payload Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3responseTff7b72.Td2a8ffbodyTb4b4b4)
Tff7b72assert Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4]Tff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4)

Tff7b72with Tffa657openTb4b4b4(Te6edf3app_instanceTff7b72.Td2a8ff_reticulum_config_file_pathTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3on_disk Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3on_disk Tff7b72== Te6edf3new_content


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_endpoint_put_rejects_missing_sectionsTb4b4b4(Te6edf3app_instanceTb4b4b4)Tb4b4b4:
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3app_instanceTb4b4b4, Ta5d6ff"Ta5d6ffPUTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/reticulum/config/rawTa5d6ff"Tb4b4b4)

Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(Te6edf3_make_requestTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffgarbageTa5d6ff"Tb4b4b4}Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff400
Te6edf3payload Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3responseTff7b72.Td2a8ffbodyTb4b4b4)
Tff7b72assert Ta5d6ff"Ta5d6ff[reticulum]Ta5d6ff" Tff7b72in Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4]


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_endpoint_put_rejects_non_string_contentTb4b4b4(Te6edf3app_instanceTb4b4b4)Tb4b4b4:
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3app_instanceTb4b4b4, Ta5d6ff"Ta5d6ffPUTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/reticulum/config/rawTa5d6ff"Tb4b4b4)

Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(Te6edf3_make_requestTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4: T79c0ff123Tb4b4b4}Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff400


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_endpoint_put_rejects_invalid_jsonTb4b4b4(Te6edf3app_instanceTb4b4b4)Tb4b4b4:
Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3app_instanceTb4b4b4, Ta5d6ff"Ta5d6ffPUTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/reticulum/config/rawTa5d6ff"Tb4b4b4)

Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(Te6edf3_make_requestTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff400


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_endpoint_reset_restores_defaultsTb4b4b4(Te6edf3app_instanceTb4b4b4)Tb4b4b4:
Te6edf3reset_handler Tff7b72= Te6edf3_find_handlerTb4b4b4(
Te6edf3app_instanceTb4b4b4,
Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/reticulum/config/resetTa5d6ff"Tb4b4b4,
Tb4b4b4)

Te6edf3config_path Tff7b72= Te6edf3app_instanceTff7b72.Td2a8ff_reticulum_config_file_pathTb4b4b4(Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3config_pathTb4b4b4)Tb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3config_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(
Ta5d6ff"Ta5d6ff[reticulum]Tffea00\nTa5d6ff enable_transport = TrueTffea00\nTffea00\nTa5d6ff"
Ta5d6ff"Ta5d6ff[interfaces]Tffea00\nTa5d6ff [[X]]Tffea00\nTa5d6ff type = AutoInterfaceTffea00\nTa5d6ff"Tb4b4b4,
Tb4b4b4)

Te6edf3response Tff7b72= Tff7b72await Te6edf3reset_handlerTb4b4b4(Te6edf3_make_requestTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Te6edf3payload Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3responseTff7b72.Td2a8ffbodyTb4b4b4)
Te6edf3expected Tff7b72= Te6edf3_rns_default_config_text_atTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3app_instanceTff7b72.Td2a8ffstorage_dirTb4b4b4, Ta5d6ff"Ta5d6ff_rns_default_refTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3payloadTb4b4b4[Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4] Tff7b72== Te6edf3expected

Tff7b72with Tffa657openTb4b4b4(Te6edf3config_pathTb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3on_disk Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3on_disk Tff7b72== Te6edf3expected


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_endpoint_get_returns_404_if_config_missingTb4b4b4(Te6edf3app_instanceTb4b4b4)Tb4b4b4:
Te6edf3config_path Tff7b72= Te6edf3app_instanceTff7b72.Td2a8ff_reticulum_config_file_pathTb4b4b4(Tb4b4b4)
Te6edf3config_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3config_pathTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3config_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3config_pathTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3config_pathTb4b4b4)
Tff7b72assert Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3config_pathTb4b4b4)

Te6edf3handler Tff7b72= Te6edf3_find_handlerTb4b4b4(Te6edf3app_instanceTb4b4b4, Ta5d6ff"Ta5d6ffGETTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/api/v1/reticulum/config/rawTa5d6ff"Tb4b4b4)
Te6edf3response Tff7b72= Tff7b72await Te6edf3handlerTb4b4b4(Te6edf3_make_requestTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3responseTff7b72.Td2a8ffstatus Tff7b72== T79c0ff404


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────